package org.marsdonne.commons;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.PropertyUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;
import java.util.Map;
import java.util.Random;

import static java.util.stream.Collectors.joining;

public class SignatureUtils {

    private SignatureUtils() {
    }

    private static final String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public static String generateRandomString(int length) {
        Random random = new Random();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < length; i++)
            builder.append(base.charAt(random.nextInt(base.length())));
        return builder.toString();
    }

    private static final String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};

    public static String byte2HexStr(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    public static String byteArray2HexStr(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes)
            builder.append(byte2HexStr(b));
        return builder.toString();
    }

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static Map convert2Map(Object obj) {
        return objectMapper.convertValue(obj, Map.class);
    }

    public static String convertToUrl(Object obj) {
        Map<String, Object> map = convert2Map(obj);

        return map.keySet().stream()
                .map(key -> {
                    try {
                        Class typeClass = PropertyUtils.getPropertyType(obj, key);
                        String value, type = typeClass.getSimpleName();

                        if (type.equals("String")) {
                            value = (String) map.get(key);
                        } else if (typeClass.isPrimitive()) {
                            value = String.valueOf(map.get(key));
                        } else {
                            value = map.get(key).toString();
                        }

                        return value != null && value.length() > 0 ? key + "=" + value : null;
                    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                        e.printStackTrace();
                    }

                    return null;
                })
                .filter(value -> value != null)
                .sorted(Comparator.naturalOrder())
                .collect(joining("&"));
    }
}
